//
//  MCNNavigationBarCategory.swift
//  MCNNavigationBarCategory
//
//  Created by yhbj on 2021/9/16.
//

import UIKit

protocol MCNBackButtonHandlerProtocol: NSObjectProtocol {
    func mcn_navSystemBarPopHandle() -> Bool
}

extension UIView {
    var mcn_x: CGFloat {
        set {
            self.frame.origin.x = newValue
        }
        get {
            return self.frame.origin.x
        }
    }
    var mcn_y: CGFloat {
        set {
            self.frame.origin.y = newValue
        }
        get {
            return self.frame.origin.y
        }
    }
    var mcn_width: CGFloat {
        set {
            self.frame.size.width = newValue
        }
        get {
            return self.frame.size.width
        }
    }
    var mcn_height: CGFloat {
        set {
            self.frame.size.height = newValue
        }
        get {
            return self.frame.size.height
        }
    }
    var mcn_top: CGFloat {
        set {
            mcn_y = newValue
        }
        get {
            return mcn_y
        }
    }
    var mcn_bottom: CGFloat {
        set {
            mcn_y = newValue - mcn_height
        }
        get {
            return mcn_y + mcn_height
        }
    }
    var mcn_left: CGFloat {
        set {
            mcn_x = newValue
        }
        get {
            return mcn_x
        }
    }
    var mcn_right: CGFloat {
        set {
            mcn_x = newValue - mcn_width
        }
        get {
            return mcn_x + mcn_width
        }
    }
    var mcn_centerX: CGFloat {
        set {
            center.x = newValue
        }
        get {
            return center.x
        }
    }
    var mcn_centerY: CGFloat {
        set {
            center.y = newValue
        }
        get {
            return center.y
        }
    }
    var mcn_origin: CGPoint {
        set {
            frame.origin = newValue
        }
        get {
            return frame.origin
        }
    }
    var mcn_size: CGSize {
        set {
            frame.size = newValue
        }
        get {
            return frame.size
        }
    }
}

extension NSString {
    func mcn_getRectWidth(limitH: CGFloat, fontSize: CGFloat) -> CGFloat {
        return boundingRect(with: CGSize.init(width: CGFloat.greatestFiniteMagnitude, height: limitH), options: .usesLineFragmentOrigin, attributes: [.font : UIFont.systemFont(ofSize: fontSize)], context: nil).width
    }
    func mcn_getRectHeight(limitW: CGFloat, fontSize: CGFloat) -> CGFloat {
        return boundingRect(with: CGSize.init(width: limitW, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: [.font : UIFont.systemFont(ofSize: fontSize)], context: nil).height
    }
}

extension NSAttributedString {
    func mcn_getAttrRectWidth(limitH: CGFloat, fontSize: CGFloat) -> CGFloat {
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: fontSize)
        label.attributedText = self
        return label.sizeThatFits(CGSize.init(width: CGFloat.greatestFiniteMagnitude, height: limitH)).width
    }
    func mcn_getAttrRectHeight(limitW: CGFloat, fontSize: CGFloat) -> CGFloat {
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: fontSize)
        label.attributedText = self
        return label.sizeThatFits(CGSize.init(width: limitW, height: CGFloat.greatestFiniteMagnitude)).height
    }
}

extension UIImage {
    func mcn_rendering(color: UIColor) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(size, false, scale)
        let context = UIGraphicsGetCurrentContext()
        context?.translateBy(x: 0, y: size.height)
        context?.scaleBy(x: 1, y: -1)
        context?.setBlendMode(.normal)
        let rect = CGRect.init(x: 0, y: 0, width: size.width, height: size.height)
        context?.clip(to: rect, mask: self.cgImage!)
        color.setFill()
        context?.fill(rect)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image!
    }
    class func mcn_imageFromBundle(imageName: String) -> UIImage? {
        var image : UIImage? = nil
        if image == nil {
            let bundle = Bundle(path: Bundle.init(for: MCNNavigationBar.classForCoder()).path(forResource: "MCNNavigationBar", ofType: "bundle")!)
            image = UIImage.init(contentsOfFile: (bundle?.path(forResource: imageName, ofType: "png"))!)?.withRenderingMode(.alwaysOriginal)
        }
        return image
    }
}

extension UINavigationController: UINavigationBarDelegate, MCNBackButtonHandlerProtocol {
    
    private static var isHideAllNavBar = false
    
    class func mcn_hideAllNavBar() {
        isHideAllNavBar = true
        UINavigationController.mcn_nav_swizzleMethod(claxx: self.classForCoder(), originSelector: #selector(pushViewController(_:animated:)), swizzleSelector: #selector(swizz_pushViewController(_:animated:)))
    }
    
    class func mcn_removeAllNavBar() {
        isHideAllNavBar = false
    }
    
    @objc func swizz_pushViewController(_ viewController: UIViewController, animated: Bool) {
        self.swizz_pushViewController(viewController, animated: animated)
        let class1: AnyClass? = NSClassFromString("MCNNavigationBarController")
        let class2: AnyClass? = NSClassFromString("MCNNavigationBarTableViewController")
        if (UINavigationController.isHideAllNavBar && (viewController.isKind(of: (class1?.class())!) || viewController.isKind(of: (class2?.class())!))) {
            self.isNavigationBarHidden = true
        }
    }
    
    private static func mcn_nav_swizzleMethod(claxx: AnyClass, originSelector: Selector, swizzleSelector: Selector) {
        guard let originMethod = class_getInstanceMethod(claxx, originSelector) else { return }
        guard let swizzleMethod = class_getInstanceMethod(claxx, swizzleSelector) else { return }
        
        let didAddMethod = class_addMethod(claxx, originSelector, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod))
        if didAddMethod {
            class_replaceMethod(claxx, swizzleSelector, method_getImplementation(originMethod), method_getTypeEncoding(originMethod))
        } else {
         method_exchangeImplementations(originMethod, swizzleMethod)
        }
    }
    
    public func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
        if viewControllers.count < navigationBar.items!.count {
            return true
        }
        var shouldPop = true
        if (topViewController?.responds(to: #selector(mcn_navSystemBarPopHandle)))! {
            shouldPop = (topViewController?.navigationController?.mcn_navSystemBarPopHandle())!
        }
        if shouldPop {
            DispatchQueue.main.async {
                self.popViewController(animated: true)
            }
        } else {
            for subView in navigationBar.subviews {
                if 0 < subView.alpha && subView.alpha < 1 {
                    UIView.animate(withDuration: 0.25) {
                        subView.alpha = 1
                    }
                }
            }
        }
        return shouldPop
    }
    
    @objc func mcn_navSystemBarPopHandle() -> Bool {
        return true
    }
}

extension UIViewController {
    
}
